package action

import (
	"fmt"
	"strings"

	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/logger"
	"gorm.io/gorm"

	"ssdevice/common/constant"
	"ssdevice/common/enums"
	"ssdevice/common/middleware/mqtt"
	"ssdevice/common/utils"
	"ssdevice/internal/data/format"
	"ssdevice/internal/device/models"
)

type Logout struct {
	Orm *gorm.DB
}

func (action *Logout) Execute(topic string, jsonData map[string]interface{}) {
	devSn := strings.Split(topic, "/")[3]
	_, to := format.GetFromTo(devSn, jsonData, false)
	// 更新状态
	dev := models.SysDev{}
	dev.Model.Orm = action.Orm
	if err := dev.UpdateOnlineStatus(devSn, to, utils.GetNowTimeStr(), enums.Offline); err != nil {
		logger.Error(err)
	}
	// 响应
	logInOutAck(devSn, to, enums.Logout.Get().Name, jsonData)
	// 广播
	pubLoginout(devSn, to, enums.LogoutMsg, jsonData)
}

func logInOutAck(devSn, to, biz string, jsonData map[string]interface{}, go2 ...string) {
	goTo := ""
	if len(go2) > 0 {
		goTo = go2[0]
	}
	ackTopic := fmt.Sprintf("/iot/%s/%s/%s/ack", devSn, constant.TopicPlaceholder, biz)
	ackData := map[string]interface{}{
		"sid":  jsonData["sid"],
		"from": constant.TopicPlaceholder,
		"to":   to,
		"code": 200,
		"msg":  "",
		"data": map[string]interface{}{
			"ak":   "",
			"goto": goTo,
		},
	}
	mqtt.MqttClient.Publish(ackTopic, utils.MapToBytes(ackData))
}

// 广播登录登出主题
func pubLoginout(devSn, to string, msgType enums.MsgType, jsonData map[string]interface{}, deptId ...string) {
	delete(jsonData, constant.CacheLoginInfo)
	targetSn := utils.If(len(to) > 0 && to != devSn, to, devSn).(string)
	cacheData := map[string]interface{}{
		"sn":         targetSn,
		"data":       jsonData,
		"updateTime": utils.GetNowTimeStr(),
		"msgType":    msgType.Get().Name,
	}
	if len(deptId) > 0 {
		cacheData["deptId"] = deptId[0]
	} else {
		dptId, _ := env.Cache.HashGet(constant.DeviceDeptCache, devSn)
		cacheData["deptId"] = dptId
	}
	dataBytes := utils.MapToBytes(cacheData)
	tp := utils.If(msgType.Get().Name == enums.LoginMsg.Get().Name, constant.LoginMsgTopic, constant.LogoutMsgTopic).(string)
	mqtt.MqttClient.Publish(tp, dataBytes)
	// 事件纪录
	cnt, _ := env.Cache.LPush(constant.DevEventCache, string(utils.MapToBytes(map[string]interface{}{
		"sn":    targetSn,
		"title": utils.If(msgType.Get().Name == enums.LoginMsg.Get().Name, "设备上线", "设备下线").(string),
		"type":  1,
		"time":  utils.GetNowTimeStr(),
	})))
	if cnt > 1000 {
		// 保留近1000条
		_, _ = env.Cache.RPop(constant.DevEventCache)
	}
}
